import os
import io
import traceback
import datetime
import urllib.parse

debug = False

Login(role="admin")

def _head():
    head = HEAD()
    head <= LINK(rel="stylesheet",href="../kftp.css")
    head <= SCRIPT(src="../kftp.js")
    return head

def _(src):
    return src
    
def index(folder=''):
    unq_folder = urllib.parse.unquote_plus(folder).split('/')
    full_folder = os.path.join(THIS.root_dir,*unq_folder)
    if not os.path.normpath(full_folder).startswith(os.path.normpath(THIS.root_dir)):
        return "Access forbidden to specified folder"
    
    body = H1('FTP')
    
    body += DIV('&nbsp;',Id="progress")
    if debug:
        body += TEXTAREA(Id="status",rows=5,cols=40)+P()
    
    body += SCRIPT('debug=%s\nfolder="%s"' %(str(debug).lower(),folder))
    
    links = '&nbsp;'
    if unq_folder:
        if folder:
            links = A('.. / ',href='index')
        for i,item in enumerate(unq_folder):
            link = urllib.parse.quote_plus('/'.join(unq_folder[:i+1]))
            if i>0:
                links += ' / '
            links += A(item,href='index?folder=%s' %link)
    
    body += DIV(links,Id="path")
    
    dirs = []
    files = []
    for path in os.listdir(full_folder):
        full = os.path.join(full_folder,path)
        if os.path.isdir(full):
            dirs.append(path)
        elif os.path.isfile(full):
            files.append(path)
    dirs.sort()
    files.sort()

    num = 0
    t = TABLE(Id="files",style="width:90%")
    if folder:
        body += SCRIPT('folder_up="%s"' %('/'.join(unq_folder[:-1])))
        row = TR()
        url = urllib.parse.quote_plus('/'.join(unq_folder[:-1]))
        row <= TD(A(IMG(src='../images/folder_up.png',border=0),
            href="index?folder=%s" %url),Class="folder_up")
        row <= TD('&nbsp;',Class="path")
        row <= TD('&nbsp;')*3
        t <= row
        num += 1
    for _dir in dirs:
        href = '/'.join(unq_folder)
        if href:
            href += '/'
        href += _dir
        href = "index?folder=%s" %urllib.parse.quote_plus(href)
            
        row = TR(onmouseover="show_menu('dir',%s)" %num,
             onmouseout="leave_cell()",Id="row_%s" %num)
        row <= TD(A(IMG(src='../images/folder.png',border=0),href=href),Class="dirpath")
        link = A(os.path.basename(_dir),href=href,Class="dirpath",Id="name_%s" %num)
        row <= TD(link,Class="path",Id="cell_%s" %num)
        link = A(IMG(src="../images/delete.png",border=0,style="display:inline"),
            title=_('Delete'),href="#",
            onclick="drop_dir(%s)" %num)
        link += '&nbsp;'+A(IMG(src="../images/rename.png",border=0,style="display:inline;"),
            title=_('Rename'),href="#",
            onclick="start_edit(%s)" %num)
        row <= TD(SPAN(link,style="visibility:hidden"),
            Id="menu_%s" %num,Class="menu")
        row <= TD('&nbsp;')*2
        t <= row
        num += 1
    for _file in files:
        filename = os.path.join(full_folder,_file)
        infos = os.stat(filename)
        row = TR(Id="row_%s" %num,
            onmouseover="show_menu('dir',%s)" %num,
            onmouseout="leave_cell()")
        row <= TD('&nbsp;',Class="path")
        url = '/'.join(unq_folder)
        if url:
            url += '/'
        url = '/'+url.lstrip('/')+urllib.parse.quote(_file)
        row <= TD(A(_file,
            href=url,target="_blank",
            Id="name_%s" %num),
            Class="path",
            Id="cell_%s" %num)
        link = A(IMG(src="../images/delete.png",border=0,style="display:inline"),
            title=_('Delete'),href="#",
            onclick="drop_file(%s)" %num)
        link += '&nbsp;'+A(IMG(src="../images/rename.png",border=0,style="display:inline;"),
            title=_('Rename'),href="#",
            onclick="start_edit(%s)" %num)
        row <= TD(SPAN(link,style="visibility:hidden"),
            Id="menu_%s" %num,Class="menu")
        row <= TD(infos.st_size,align="right")
        last_modif = datetime.datetime.fromtimestamp(infos.st_mtime)
        row <= TD(last_modif.strftime('%Y-%m-%d %H:%M'))
        t <= row
        num += 1

    cell = TD()
    
    form = FORM(action="upload",method="post",enctype="multipart/form-data")
    form <= INPUT(Type="hidden",name="folder",value=folder)
    form <= _("Upload file")+BR(_('or drag-and-drop into file list'))+BR()
    form <= INPUT(Type="file",name="src")
    form <= INPUT(Type="submit",value="Ok")
    cell <= form

    form = FORM(action="create_folder",method="post")
    form <= INPUT(Type="hidden",name="folder",value=folder)
    line = _("Create folder")+BR()+INPUT(name="new_name")
    line += INPUT(Type="submit",value="Ok")
    form <= line
    
    cell <= form
    additems = TABLE(TR(cell),Class="additems")

    body += TABLE(TR(TD(t,style="width:50%;",valign="top")+TD(additems,valign="top")),width="90%")
    
    upload_infos = DIV(Id="upload_info")
    upload_infos <= DIV("&nbsp;",Id="messages")
    upload_infos <= DIV(DIV("0%",Id="pcbar"),Id="progress_bar")
    body += upload_infos
        
    body += SCRIPT(src="../filedrag.js")

    return HTML(_head()+BODY(body))

def upload(folder,src):
    filename = src.filename
    dest_dir = os.path.join(THIS.root_dir,urllib.parse.unquote_plus(folder))
    import shutil
    dest_fileobj = open(os.path.join(dest_dir,filename),'wb')
    shutil.copyfileobj(src.file,dest_fileobj)
    raise HTTP_REDIRECTION('index?folder=%s' %folder)

def upload_dd(folder,src):
    # upload by drag and drop
    import re
    import base64
    dest_dir = os.path.join(THIS.root_dir,urllib.parse.unquote_plus(folder))
    dest_path = os.path.join(dest_dir,src.filename)
    content = src.value
    # unparse data url
    pattern = b"data:(?P<type>.+?);base64,(?P<data>.*)"
    mo = re.match(pattern,content)
    if not mo:
        return "Invalid data"
    typ = mo.group('type')
    data = mo.group('data')
    content = base64.b64decode(data)
    out = open(dest_path,'wb')
    out.write(content)
    out.close()
    return "ok"

def file_exists(folder,name):
    return os.path.exists(os.path.join(THIS.root_dir,
        urllib.parse.unquote_plus(folder),name))
        
def read_file(name):
    path = urllib.parse.unquote_plus(name)
    import mimetypes
    gtype,encoding = mimetypes.guess_type(name)
    RESPONSE_HEADERS['Content-type'] = gtype
    data = open(path,'rb').read()
    return data

def delete(**kw):
    src = kw['src'].lstrip()
    folder = kw.get('folder','')
    dest_dir = os.path.join(THIS.root_dir,urllib.parse.unquote_plus(folder))
    if not os.path.normpath(dest_dir).startswith(os.path.normpath(THIS.root_dir)):
        return "Access forbidden to specified folder"
    path_type = kw["path_type"]
    if path_type=="file":
        dest_file = os.path.join(dest_dir,src)
        try:
            os.remove(dest_file)
            return "ok"
        except:
            trace = io.StringIO()
            traceback.print_exc(file=trace)
            return trace.getvalue()
    elif path_type=="dir":
        dest_dir = os.path.join(dest_dir,src)
        if os.listdir(dest_dir):
            return _("Folder is not empty")
        try:
            os.rmdir(dest_dir)
            return "ok"
        except:
            trace = io.StringIO()
            traceback.print_exc(file=trace)
            return trace.getvalue()

def rename(**kw):
    folder = urllib.parse.unquote_plus(kw.get("folder",''))
    initial_name = kw['old_name']
    new_name = kw.get('new_name',None)
    if new_name is None:
        return "Error - The new name is empty"
    try:
        os.rename(os.path.join(folder,initial_name),
            os.path.join(folder,new_name))
        return "ok"
    except:
        trace = io.StringIO()
        traceback.print_exc(file=trace)
        return trace.getvalue()

def create_folder(**kw):
    folder = urllib.parse.unquote_plus(kw.get("folder",''))
    new_name = urllib.parse.unquote_plus(kw.get("new_name",''))
    if not new_name:
        return _("missing new folder name")
    new_folder = os.path.join(folder,new_name)
    if os.path.exists(new_folder):
        return _("this folder already exists")
    os.mkdir(new_folder)
    raise HTTP_REDIRECTION("index?folder=%s" %folder)

def show(folder,path):
    folder = urllib.parse.unquote_plus(folder)
    path = urllib.parse.unquote_plus(path)
    import mimetypes
    gtype,encoding = mimetypes.guess_type(path)
    RESPONSE_HEADERS['Content-type'] = gtype
    data = open(os.path.join(folder,path),'rb').read()
    return data